package com.jianggy.chainofrespon.json;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @author jianggy
 * @time 2018年9月13日 上午10:16:38
 * @description
 */
public class HandlerChainFactory {
	@SuppressWarnings("unchecked")
	public static HandlerChain getInstance() throws MalformedURLException, URISyntaxException, ClassNotFoundException,
			InstantiationException, IllegalAccessException {
		HandlerChain chain = new HandlerChain();
		List<String> list = scan("com.jianggy.chainofrespon.json");
		for (String className : list) {
			Class<Handler> clazz = (Class<Handler>) Class.forName(className.replace(".class", ""));
			Annotation annotation = clazz.getAnnotation(HandlerAnnotation.class);
			if (annotation != null) {
				chain.addHandler(clazz.newInstance());
			}
		}
		return chain;
	}

	/**
	 * 扫描指定packageName包下的class文件
	 * @param packageName
	 * @return
	 * @throws MalformedURLException
	 * @throws URISyntaxException
	 */
	public static List<String> scan(String packageName) throws MalformedURLException, URISyntaxException {
		List<String> classNames = new ArrayList<>();
		String packagePath = packageName.replace(".", "/");
		URL url = Thread.currentThread().getContextClassLoader().getResource("");
		String classPath = url.toString() + packagePath;
		doScan(classPath, classNames, packageName);
		return classNames;

	}

	/**
	 * 执行具体的文件扫描
	 * @param classPath
	 * @param classNames
	 * @param packageName
	 * @throws MalformedURLException
	 * @throws URISyntaxException
	 */
	public static void doScan(String classPath, List<String> classNames, String packageName)
			throws MalformedURLException, URISyntaxException {
		File file = new File(new URL(classPath).toURI());
		File[] nextFiles = file.listFiles();
		for (File f : nextFiles) {
			if (f.isDirectory()) {
				doScan(classPath + "/" + f.getName(), classNames, packageName + "." + f.getName());
			} else if (f.getName().endsWith(".class")) {
				classNames.add(packageName + "." + f.getName());
			}
		}
	}

}
